package cz.muni.fi.pa165.languageschool.rest;

import cz.muni.fi.pa165.languageschool.DataFetchException;
import cz.muni.fi.pa165.languageschool.dto.StudentTO;
import cz.muni.fi.pa165.languageschool.service.StudentService;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * REST students resource
 *
 * @author Michal Fucik (3956224) michal.fuca.fucik(at)gmail.com
 */
@Component
@Path("/students")
@Singleton
public class StudentsResource {

    private StudentService studentService;
    final static Logger log = LoggerFactory.getLogger(StudentsResource.class);
    @Context
    private UriInfo context;

    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }

    // tahle metoda by mela byt imho odstranena, nejak nechapu k cemu nam je
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getPlain() {
        StringBuilder res = new StringBuilder();
        try {
            if (studentService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }

            for (StudentTO sto : studentService.getAllStudents()) {
                res.append(sto.toString());
                res.append(",");
            }
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return res.toString();
    }

    @GET
    @Path("{json}")
    @Produces(MediaType.APPLICATION_JSON)
    public List<StudentResource> getAllStudents() {
        List<StudentResource> list = new ArrayList<>();
        try {
            if (studentService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }

            for (StudentTO sto : studentService.getAllStudents()) {
                list.add(new StudentResource(sto));
            }
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return list;
    }

    // tahle metoda by mela byt imho odstranena, pac nevim k cemu nam je
    @Path("{id}")
    public StudentResource getStudentResource(@PathParam("id") Integer id) {
        StudentTO sto = null;
        StudentResource crs = null;
        try {
            if (studentService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            sto = studentService.getStudent(new Long(id));
            crs = new StudentResource(sto);
            System.out.println();
            System.out.println("StudentsResource getStudentResource id " + id + "    " + sto);
            System.out.println();
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return crs;
    }

    @GET
    @Path("json/{id}")
    @Produces({MediaType.APPLICATION_JSON})
    public StudentResource getStudent(@PathParam("id") Integer id) {
        StudentTO sto = null;
        StudentResource crs = null;
        try {
            if (studentService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            sto = studentService.getStudent(new Long(id));
            crs = new StudentResource(sto);
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return crs;
    }
    // {"id":"99","code":"COOODE","name":"NEW COURSE","taughtLanguage":"CZECH","requiredLevel":"NEW"}

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createStudent(StudentResource studentResource) {
        try {
            if (studentService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            studentResource.setId(null);
            studentService.createStudent((StudentTO) studentResource);
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }
        log.info("Student created id = " + studentResource.getId());
        return Response.created(URI.create(context.getAbsolutePath() + "/" + studentResource.getId())).build();
    }

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updateStudent(StudentResource studentResource) {
        try {
            if (studentService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            studentService.updateStudent((StudentTO) studentResource);
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        log.info("Student updated to = " + studentService.toString());
        return Response.created(URI.create(context.getAbsolutePath() + "json/" + studentResource.getId())).build();
    }

    @DELETE
    @Path("{id}")
    public Response deleteStudent(@PathParam("id") Integer id) {
        StudentTO sto = new StudentTO();
        sto.setId(new Long(id));
        try {
            if (studentService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            studentService.deleteStudent(sto);
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        log.info("Student deleted id = " + id);
        return Response.status(Response.Status.OK).build();
    }

}
